/* ***** BEGIN LICENSE BLOCK *****
 * Version: NPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Netscape Public License
 * Version 1.1 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.mozilla.org/NPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is lutsko.com code.
 *
 * The Initial Developer of the Original Code is 
 * James Lutsko.
 * Portions created by the Initial Developer are Copyright (C) 2003
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the NPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the NPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

package autoteam;

import java.io.*;
import java.util.*;

import jxl.*; 

/**
 * The data come in as a table with row headers and columns giving
 * the values for each child. The role of the DataMap class is to 
 * be able to:
 * - map column numbers to fields used in the program 
 *    (e.g., field 3 = lastName)
 * - to provide mapping from program field names to columns
 *    (e.g. lastName = field 3)
 * - to remember which fields are skills
 *
 * This mapping is meant to be persistant so that it can be reused
 * with different data files.
 *
 * There is one map per league.
 *
 *@author JFL
 */

public class DataMap implements Serializable 
{
    public static final String[] fieldNames = {"Ignore",
					       "Last Name", 
					       "First Name",
					       "Phone",
					       "Email",
					       "ID",
					       "Comment",
					       "Height",
					       "Experience",
					       "BadNights",
					       "GoodNights",
    };

    public static final String SkillString = new String("Skill");
    public static final String SkillBreakString = new String("--------Skills-------");

    /**
     * The i-th entry is the dataFieldColumn of the 
     * i-th skill field.
     */
    public int[] skillFields = null;
    
    /**
     * Given index in fieldNames array, gives position in header array
     * In other words, this translates from our indexing to that of the 
     * data file.
     */
    public int[] dataFileColumn = null; 

    /**
     * the header fields from the file
     */
    public String[] headerFields = null;


    /**
     * The file from which we try to read the datamapping. Whatever mapping
     * is constructed is then written back to this file.
     */
    File mapFile = null;

    /** 
     * The number of skill fields.
     */

    public int getSkillNumber(){ return skillFields.length;}

    /**
     * Translates the String passed in value into a position
     * by looping through the fieldNames array and using ==.
     */

    public void setElement(Object value, int pos)
    {
	for(int i=0;i<fieldNames.length;i++)
	    if(fieldNames[i] == value)
		dataFileColumn[i] = pos;
    }


    public void initializeMappings(Vector valueAt)
    {
	// If a map file was read, fill in the values of the mapping.
	// The first test is a sanity check.
	// N.B. DataMap.dataFileColumn[i] is the mapping from DataMap.fieldNames
	// into the data array. (The inverse of valueAt.)
	//

	valueAt.setSize(headerFields.length);

	for(int i=0;i<headerFields.length;i++)
		valueAt.set(i,fieldNames[0]);

	if(headerFields != null)
	    for(int i=0;i<dataFileColumn.length;i++)
		{
		    if(dataFileColumn[i] != -1)
			valueAt.set(dataFileColumn[i], fieldNames[i]);
		}

	if(skillFields != null)
	    for(int i=0;i<skillFields.length;i++)
		{
		    if(skillFields[i] != -1)
			valueAt.set(skillFields[i], SkillString);
		}
    }
    /**
     * Looks up the skill name. First, the
     * index of skill field pos is looked up
     * in skillFields[] and then this index
     * is translated using headerFields[].
     */

    public String getSkillName(int pos)
    {
	if(pos < skillFields.length && pos >= 0)
	    return headerFields[skillFields[pos]];
	return null;
    }

    /**
     * Translates a skill name into the index
     * of the field in the skillNames[] array.
     */

    public int skillFromName(String name)
    {
	for(int i=0;i<skillFields.length;i++)
	    if(getSkillName(i).equals(name))
		return i;
	return -1;
    }


    public DataMap(File f)
    {
	dataFileColumn = new int[fieldNames.length];
	for(int i=0;i<dataFileColumn.length;i++) dataFileColumn[i] = -1;
	
	if(f != null) readFile(f);
    }


    public DataMap(File f, Sheet s)
    {
	dataFileColumn = new int[fieldNames.length];
	for(int i=0;i<dataFileColumn.length;i++) dataFileColumn[i] = -1;
	
	readSheet(f,s);
    }

    /**
     * Creates and fills the skillFields array.
     *
     * @param map The i-th entry gives the mapped value
     * of the i-th headerField into the fieldNames array.
     */
    public void setSkills(Vector map)
    {
	// count the number of skill fields.
	//
	int c = 0;
	for(int i=0;i<map.size();i++)
	    if(map.get(i) == SkillString)
		c++;
	skillFields = new int[c];

	// fill in the skillFields array.
	c = 0;
	for(int i=0;i<map.size();i++)
	    if(map.get(i) == SkillString)
		skillFields[c++] = i; 

	// write the map file
	try {
	    BufferedWriter out = new BufferedWriter(new FileWriter(mapFile));
	    BufferedWriter out2 = new BufferedWriter(new FileWriter(new File(mapFile.getParent(),"map.map")));
	    for(int i=0;i<dataFileColumn.length;i++)
		{
		    String s = Integer.toString(dataFileColumn[i]); 
		    out.write(s,0,s.length());out.newLine();
		    out2.write(s,0,s.length());out2.newLine();
		}

	    // write the magic string separating the skills section
	    out.write(SkillBreakString,0,SkillBreakString.length());out.newLine();
	    out2.write(SkillBreakString,0,SkillBreakString.length());out2.newLine();
	    // write the number of skills
	    int num = (skillFields == null ? 0 : skillFields.length);
	    String ss = Integer.toString(num); 
	    out.write(ss,0,ss.length());out.newLine();
	    out2.write(ss,0,ss.length());out2.newLine();

	    for(int i=0;i<skillFields.length;i++)
		{
		    String s = Integer.toString(skillFields[i]); 
		    out.write(s,0,s.length());out.newLine();
		    out2.write(s,0,s.length());out2.newLine();
		}
	    out.close();
	    out2.close();
	}catch(java.io.IOException e) {};

    }
	
    public Double getSkillField(int i, String[] fields)
    {
	// We cannot use getDoubleField because this takes
	// us through the dataFileColumn mapping which doesn't apply
	// for skill fields.
	//	return getDoubleField(skillFields[i],fields);
	int f = skillFields[i];
	String s =  ((f >= 0) && (f < fields.length) ? fields[f].trim() : null);
	return (s == null || s.length() < 1 ? null : Double.valueOf(s));
    }

    public String getStringField(int i, String[] fields)
    {
	int f = dataFileColumn[i]; 
	return ((f >= 0) && (f < fields.length) ? fields[f].trim() : null);
    }

    public Integer getIntField(int i, String[] fields)
    {
	String s  = getStringField(i,fields);
	return (s == null || s.length() < 1 ? null : new Integer(s));
    }

    public Double getDoubleField(int i, String[] fields)
    {
	System.out.println("i = " + i + " fields.length = "+ fields.length);
	String s  = getStringField(i,fields);
	return (s == null || s.length() < 1 ? null : Double.valueOf(s));
    }

    public int getIntValueField(int i, String[] fields)
    {
	String s  = getStringField(i,fields);
	return (s == null || s.length() < 1 ? 0 : Integer.parseInt(s));
    }

    void readFile(File f)
    {
	try {
	    FileReader in = new FileReader(f);
	    BufferedReader d = new BufferedReader(in);
	    String input;
	    
	    input = d.readLine();

	    headerFields = input.split(",",-1);

	    d.close();
	  
	    readMapFile(f);
	}catch(java.io.IOException e) {};

    }


    void readSheet(File f, Sheet s)
    {
	//	try {
	    int ncol = s.getColumns();
	    Vector fields = new Vector();
	    for(int i=0;i<ncol;i++)
		{
		    Cell cell = s.getCell(i,0);
		    if(cell == null) break;
		    Object val = cell.getContents(); 
		    if(val == null) break;
		    fields.add(val.toString());
		}
	    headerFields = new String[fields.size()];
	    for(int i=0;i<headerFields.length;i++)
		{
		    headerFields[i] = fields.get(i).toString();
		    System.out.println("headerFields[" + i + "] = " + headerFields[i]);
		}

	    readMapFile(f);

	    //	} catch(java.io.IOException e) {};
    }

    void readMapFile(File f)
    {
	try{
	    
	    // try to read the map if it exists
	    
	    mapFile = new File(f.getAbsolutePath() + ".map");

	    File validMapFile = mapFile;

	    if(!validMapFile.exists())
		validMapFile = new File(f.getParent(),"map.map");
	    
	    if(validMapFile.exists())
		{
		    String input;

		    System.out.println("validMapFile is " + validMapFile.getName());

		    FileReader in = new FileReader(validMapFile);
		    BufferedReader d = new BufferedReader(in);
		    for(int field = 0; (input = d.readLine()) != null; field++)
			{
			    if(field < dataFileColumn.length)
				dataFileColumn[field] = Integer.parseInt(input); 
			    if(input.equals(SkillBreakString)) break;
			}
		    // read number of skill fields
		    input = d.readLine();
		    if(input != null)
			{
			    int num = Integer.parseInt(input); 
			    if(num > 0)
				{
				    skillFields = new int[num];
				    for(int field = 0; (input = d.readLine()) != null; field++)
					{
					    if(field < skillFields.length)
						skillFields[field] = Integer.parseInt(input); 
					}
				}
			}
		    d.close();
		}
	}catch(java.io.IOException e) {};
	
    }

    static final long serialVersionUID = 5425829792164544871L;
};
